﻿#pragma once
#include "AsDefine.h"
#define AS_ARG_T(t) (int)t
#define AS_ARG_N( \
	a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, \
	b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, \
	c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, \
	d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, \
	e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, \
	f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, \
	g0, g1, g2, g3, g4, g5, g6, g7, g8, g9, \
	h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, \
	i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, \
	j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, N, M, ... \
) ((N == M + 1) ? ((N == 1) ? ((#a0)[0] != 0) : N) : -1)
#define AS_ARG_N_HELPER(...) AS_ARG_T(AS_ARG_N(__VA_ARGS__))
#define AS_COUNT_ARGS(...) AS_ARG_N_HELPER(##__VA_ARGS__, \
	100, 99, 98, 97, 96, 95, 94, 93, 92, 91,  \
	90, 89, 88, 87, 86, 85, 84, 83, 82, 81,  \
	80, 79, 78, 77, 76, 75, 74, 73, 72, 71,  \
	70, 69, 68, 67, 66, 65, 64, 63, 62, 61,  \
	60, 59, 58, 57, 56, 55, 54, 53, 52, 51,  \
	50, 49, 48, 47, 46, 45, 44, 43, 42, 41,  \
	40, 39, 38, 37, 36, 35, 34, 33, 32, 31,  \
	30, 29, 28, 27, 26, 25, 24, 23, 22, 21,  \
	20, 19, 18, 17, 16, 15, 14, 13, 12, 11,  \
	10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1 \
)
#define AS_CONTA_FUNC_DEF(ARG) ((#ARG)[0]-'_')?define(&ARG, ARG, #ARG):void();
#define AS_CONTA_CALL_TMP(F, \
	A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, \
	B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, \
	C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, \
	D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, \
	E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, \
	F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, \
	G0, G1, G2, G3, G4, G5, G6, G7, G8, G9, \
	H0, H1, H2, H3, H4, H5, H6, H7, H8, H9, \
	I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, \
	J0, J1, J2, J3, J4, J5, J6, J7, J8, J9, ...) \
	F(A0)F(A1)F(A2)F(A3)F(A4)F(A5)F(A6)F(A7)F(A8)F(A9) \
	F(B0)F(B1)F(B2)F(B3)F(B4)F(B5)F(B6)F(B7)F(B8)F(B9) \
	F(C0)F(C1)F(C2)F(C3)F(C4)F(C5)F(C6)F(C7)F(C8)F(C9) \
	F(D0)F(D1)F(D2)F(D3)F(D4)F(D5)F(D6)F(D7)F(D8)F(D9) \
	F(E0)F(E1)F(E2)F(E3)F(E4)F(E5)F(E6)F(E7)F(E8)F(E9) \
	F(F0)F(F1)F(F2)F(F3)F(F4)F(F5)F(F6)F(F7)F(F8)F(F9) \
	F(G0)F(G1)F(G2)F(G3)F(G4)F(G5)F(G6)F(G7)F(G8)F(G9) \
	F(H0)F(H1)F(H2)F(H3)F(H4)F(H5)F(H6)F(H7)F(H8)F(H9) \
	F(I0)F(I1)F(I2)F(I3)F(I4)F(I5)F(I6)F(I7)F(I8)F(I9) \
	F(J0)F(J1)F(J2)F(J3)F(J4)F(J5)F(J6)F(J7)F(J8)F(J9)
#define AS_CONTA_CALL_DEFS(...) AS_ARG_T(AS_CONTA_CALL_TMP(AS_CONTA_FUNC_DEF, __VA_ARGS__))
#define AS_CONTA_OBJECT_CONSTRUCT(DEFS) private: void construct() override { DEFS }
#define AS_CONTA_OBJECT_CONSTRUCT_B(SCOPE, DEFS) void SCOPE::construct() { DEFS }
#define AS_PROPERTY(...) AS_CONTA_OBJECT_CONSTRUCT(AS_CONTA_CALL_DEFS(##__VA_ARGS__, \
	_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, \
	_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, \
	_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, \
	_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, \
	_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ ))
#define AS_PROPERTY_B(SCOPE, ...) AS_CONTA_OBJECT_CONSTRUCT_B(SCOPE, AS_CONTA_CALL_DEFS(##__VA_ARGS__, \
	_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, \
	_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, \
	_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, \
	_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, \
	_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ ))
#define AS_OBJECT_COPY(__objname__) public: \
__objname__(const AsObject& object) { from(object); } \
__objname__& operator=(const AsObject& object) { from(object); return *this; }
#define AS_OBJECT(__objname__) public: __objname__() {} AS_OBJECT_COPY(__objname__) 
#define AS_OBJECT_B(__objname__) public: __objname__() {} AS_OBJECT_COPY(__objname__) private: void construct() override;
#define AS_CUSTOMDATA_COPY(__dataname__) public: \
__dataname__(const AsCustomData& data) { from(data); } \
__dataname__& operator=(const AsCustomData& data) { from(data); return *this; } 
#define AS_CUSTOMDATA(__dataname__)  public: __dataname__() {} AS_CUSTOMDATA_COPY(__dataname__)

class AsPointCloud;

namespace As {

	AS_MEMBER_CLASS_DECLARATION(Container);

	typedef void*					Pointer;

	typedef bool						Bool;
	typedef char						Int8;
	typedef short						Int16;
	typedef int							Int;
	typedef long						Int32;
	typedef long long					Int64;
	typedef unsigned char				uInt8;
	typedef unsigned short				uInt16;
	typedef unsigned int				uInt;
	typedef unsigned long				uInt32;
	typedef unsigned long long			uInt64;
	typedef float						Float;
	typedef double						Double;
	typedef std::string					String;

	typedef AsPointCloud				PointCloud;

	typedef cv::Point					cvPoint;
	typedef cv::Point2f					cvPoint2f;
	typedef cv::Point2d					cvPoint2d;
	typedef cv::Point3f					cvPoint3f;
	typedef cv::Rect					cvRect;
	typedef cv::RotatedRect				cvRotatedRect;
	typedef cv::Mat						cvMat;

	typedef std::vector<Int>			IntArray;
	typedef std::vector<Int64>			Int64Array;
	typedef std::vector<Float>			FloatArray;
	typedef std::vector<Double>			DoubleArray;
	typedef std::vector<String>			StringArray;

	typedef std::vector<cvPoint>		cvPointArray;
	typedef std::vector<cvPoint2f>		cvPoint2fArray;
	typedef std::vector<cvPoint2d>		cvPoint2dArray;
	typedef std::vector<cvPoint3f>		cvPoint3fArray;
	typedef std::vector<cvRect>			cvRectArray;
	typedef std::vector<cvRotatedRect>	cvRotatedRectArray;
	typedef std::vector<cvMat>			cvMatArray;

	struct AS_BASIC_EXPORT _VariantType {
		enum Enum {
			Null,
			Object,
			Pointer,
			Bool,
			Int8,
			Int16,
			Int,
			Int32,
			Int64,
			uInt8,
			uInt16,
			uInt,
			uInt32,
			uInt64,
			Float,
			Double,
			String,
			PointCloud,
			cvPoint,
			cvPoint2f,
			cvPoint2d,
			cvPoint3f,
			cvRect,
			//cvRotatedRect,
			cvMat,
			IntArray,
			Int64Array,
			FloatArray,
			DoubleArray,
			StringArray,
			cvPointArray,
			cvPoint2fArray,
			cvPoint2dArray,
			cvPoint3fArray,
			cvRectArray,
			//cvRotatedRectArray,
			cvMatArray,
			Variant,
			VariantPair,
			VariantArray,
			CustomData,
			ErrorType,
		};
	};
	typedef _VariantType::Enum VariantType;

	class Variant;
	class Object;
	class CustomData;

	typedef std::pair<Variant, Variant> VariantPair;
	typedef std::vector<Variant> VariantArray;

	const std::string VariantSuffixName = ".avar";
	const std::string ContainerSuffixName = ".aconta";

	template <typename _Type>
	_Type& ref(Pointer pointer) {
		return *reinterpret_cast<_Type*>(pointer);
	}

	template <typename _Type>
	_Type* ptr(Pointer pointer) {
		return reinterpret_cast<_Type*>(pointer);
	}

};

typedef As::Variant AsVariant;
typedef As::Object AsObject;
typedef As::VariantPair AsVariantPair;
typedef As::VariantArray AsVariantArray;
typedef As::CustomData AsCustomData;

